/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.jfonia.notation;

import org.jfonia.connect5.intervals.BasicIntInterval;
import org.jfonia.connect5.relations.Equal;
import org.jfonia.model.elements.Beat;
import org.jfonia.model.elements.IStaffElement;
import org.jfonia.model.elements.MusicalElement;
import org.jfonia.model.elements.Tone;

/**
 *
 * @author Rik Bauwens
 */
public abstract class ObservableNoteOrRest extends MusicalElement implements IStaffElement
{
        private boolean locked;

        protected StaffElementSequence parentSequence;
        protected Tone tone;
        protected Beat beat;
        protected BasicIntInterval noteLength;

        public ObservableNoteOrRest(StaffElementSequence parentSequence,
                                    Tone tone, BasicIntInterval noteLength)
        {
                super(noteLength.getDifference());
                this.parentSequence = parentSequence;
                this.tone = tone;
                this.noteLength = noteLength;
                new Equal<Integer>(noteLength.getBeginNode(), getBeginNode());
                new Equal<Integer>(noteLength.getDifferenceNode(), getDifferenceNode());
        }

        protected void setMusicalTime(NoteOrRest noteOrRest)
        {
                setMusicalTime(MusicalTime.toMusicalTime(noteOrRest));
        }

        private void setMusicalTime(int musicalTime)
        {
                if(!requestLock())
                        return;
                parentSequence.requestLock();
                //Lock performance before changing
                parentSequence.getToneSequence().setLockPerformance(true);
                setDifference(musicalTime);
                //Unlock performance after changes had been applied
                parentSequence.getToneSequence().setLockPerformance(false);
                parentSequence.removeLock();
                removeLock();
        }

        public Tone getTone()
        {
                return tone;
        }

        public ObservableNoteOrRest setBeat(Beat beat)
        {
                this.beat = beat;
                return this;
        }

        public void remove()
        {
                setMusicalTime(0);
        }

        protected boolean requestLock()
        {
                if(locked)// || !parentSequence.requestLock())
                        return false;
                else
                {
                        locked = true;
                        return true;
                }
        }

        protected final void removeLock()
        {
                locked = false;
                //parentSequence.removeLock();
        }
}
